home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / mail / readers / xmail_1.000 / xmail_1 / xmail_1.6 / utils.c < prev    next >
C/C++ Source or Header  |  1995-01-30  |  14KB  |  480 lines

  1. /*
  2.  * xmail - X window system interface to the mail program
  3.  *
  4.  * Copyright 1990,1991,1992 by National Semiconductor Corporation
  5.  *
  6.  * Permission to use, copy, modify, and distribute this software and its
  7.  * documentation for any purpose is hereby granted without fee, provided that
  8.  * the above copyright notice appear in all copies and that both that
  9.  * copyright notice and this permission notice appear in supporting
  10.  * documentation, and that the name of National Semiconductor Corporation not
  11.  * be used in advertising or publicity pertaining to distribution of the
  12.  * software without specific, written prior permission.
  13.  *
  14.  * NATIONAL SEMICONDUCTOR CORPORATION MAKES NO REPRESENTATIONS ABOUT THE
  15.  * SUITABILITY OF THIS SOFTWARE FOR ANY PURPOSE.  IT IS PROVIDED "AS IS"
  16.  * WITHOUT EXPRESS OR IMPLIED WARRANTY.  NATIONAL SEMICONDUCTOR CORPORATION
  17.  * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED
  18.  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  IN NO
  19.  * EVENT SHALL NATIONAL SEMICONDUCTOR CORPORATION BE LIABLE FOR ANY SPECIAL,
  20.  * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  21.  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  22.  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  23.  * PERFORMANCE OF THIS SOFTWARE.
  24.  *
  25.  * The following software modules were created and are Copyrighted by
  26.  * National Semiconductor Corporation:
  27.  *
  28.  * 1. markIndex:
  29.  * 2. LastNumber:
  30.  * 3. SelectionNumber:
  31.  * 4. SetCursor: and
  32.  * 5. SetXY.
  33.  *
  34.  * Author:  Michael C. Wagnitz - National Semiconductor Corporation
  35.  *
  36.  */
  37.  
  38.  
  39. #include <ctype.h>
  40. #include "global.h"
  41. #include "patchlevel.h"
  42. #include "revtable.h"
  43.  
  44.  
  45. /*
  46. ** @(#)Bell() - write a status message and (optionally) ring the terminal bell
  47. */
  48. void
  49. Bell(String msg)
  50. {
  51.  Arg        args[1];
  52.  char        *p;
  53.  char        buf[BUFSIZ];
  54.  int        size;
  55.  static int    worthy = 0;        /* only msgs with ending newline are */
  56.  
  57.  
  58.  size = (int)strlen(msg);
  59.  if (size >= BUFSIZ) size = BUFSIZ - 1;
  60.  
  61.  (void) strncpy(buf, msg, size);
  62.  buf[size] = '\0';
  63.  
  64.  p = strchr(buf, '\n');            /* messages with newline get a bell */
  65. /*
  66. ** Because we have now added enter/leave window event information messages,
  67. ** we must play a slight game with incoming messages, to prevent any error
  68. ** messages from a menu selection failure or status messages from a command
  69. ** button being overwritten by the subsequent event info messages produced
  70. ** when the menu popup is dismissed or the command completes.  To do this,
  71. ** we make the bell worthy-ness flag static, and only replace a message after
  72. ** first seeing a non-default status message, which will reset the worthy-ness
  73. ** flag, but otherwise be ignored.  When the first non-default, non-error
  74. ** message comes in, simply reset our bell worthy-ness flag and return, leaving
  75. ** the previous error message still intact.  This means, to ensure seeing the
  76. ** default message, first send a blank line to reset the worthy-ness flag.
  77. */
  78.  if (! XMail.Show_Info)            /* if NOT showing info flags always */
  79.     worthy = 0;                /* reset the bell worthy-ness flag */
  80.  else {
  81.     if (worthy && p == NULL) {        /* if last was but this ain't urgent */
  82.        if (strcmp(buf, Default_Status_Info))    /* and not the default info */
  83.           worthy = 0;            /* reset the bell worthy-ness flag */
  84.        return;                /* ignore event info if menu errored */
  85.       }                    /* by leaving previous error message */
  86.    }
  87.  
  88.  if (size == 0)                /* if intent was just to reset flag */
  89.     return;
  90.  
  91.  if (p != NULL) {            /* Only display first line of output */
  92.     *p = '\0';                /* (no new line at end of label) */
  93.     worthy = 1;                /* this message is worthy of a bell */
  94.    }
  95.  
  96.  if (worthy && XMail.bellRing)        /* ring bell if not silenced by user */
  97.     XBell(XtDisplay (toplevel), 33);
  98.  
  99.  XtSetArg(args[0], XtNlabel, (XtArgVal) buf);    /* show this message text */
  100.  XtSetValues(XtNameToWidget(toplevel, "topBox.statusWindow"), args, 1);
  101.  XFlush(XtDisplay(toplevel));
  102. } /* Bell */
  103.  
  104.  
  105. /*
  106. ** @(#)figureWidth() - determine the figure width of the specified font
  107. */
  108. int
  109. figureWidth(XFontStruct *font)
  110. {
  111.  Atom        _XA_FIGURE_WIDTH;
  112.  unsigned long    width = 0;
  113.  
  114.  
  115.  _XA_FIGURE_WIDTH = XInternAtom(XtDisplay(toplevel), "FIGURE_WIDTH", FALSE);
  116.  if ((_XA_FIGURE_WIDTH != (Atom)NULL) &&
  117.     ((! XGetFontProperty(font, _XA_FIGURE_WIDTH, &width)) || (width == 0)))
  118.     if (font->per_char && font->min_char_or_byte2 <= '$' &&
  119.                           font->max_char_or_byte2 >= '$')
  120.        width = font->per_char['$' - font->min_char_or_byte2].width;
  121.     else
  122.        width = font->max_bounds.width;
  123.  
  124.  return(width);
  125. } /* end - figureWidth */
  126.  
  127.  
  128.  
  129. /*
  130. ** @(#)markIndex() - add or remove a tag from the start of a mail header line
  131. **                   May be invoked by button press, which sets the insertion
  132. **                   pointer for the text to the current mouse cursor location.
  133. */
  134. void
  135. markIndex(char *s)
  136. {
  137.  int            size;
  138.  XawTextPosition    pos, old;
  139.  String            c, p = NULL;
  140.  char            buf[3];
  141.  Widget            iw = XtNameToWidget(toplevel, "topBox.indexWindow");
  142.  Arg            args[1];
  143.  XawTextBlock        text;
  144.  
  145.  
  146.  (void) strcpy(buf, s);            /* make a copy of our marker string */
  147.  
  148.  XtSetArg(args[0], XtNstring, &p);    /* retrieve the current index buffer */
  149.  XtGetValues(iw, args, 1);
  150.  
  151.  for (pos = XawTextGetInsertionPoint(iw); pos > 0 && p[pos-1] != '\n'; pos--);
  152.  
  153.  if (buf[0] == '>') {            /* if mark is for 'current' pointer */
  154.     XtSetArg(args[0], XtNstring, &p);    /* retrieve the current index buffer */
  155.     XtGetValues(iw, args, 1);
  156.  
  157.     if ((int)strlen(p) < 3)            /* trap for case of no index at all */
  158.        return;
  159.  
  160.     if ((int)strlen(p) > pos + 1)
  161.        if (p[pos + 1] == 'S')        /* keep the Save marker if it exists */
  162.           if ((int)strlen(buf) > 1)
  163.              buf[1] = '\0';
  164.  
  165.     for (c = p; *c; c++)
  166.         if (*c == '>' && (c == p || *(c - 1) == '\n')) {
  167.            old = c - p;            /* if found, remove the old '>' mark */
  168.            text.firstPos = 0;
  169.            text.length   = 1;
  170.            text.ptr      = " ";
  171.            text.format   = FMT8BIT;
  172.            XawTextReplace(iw, (XawTextPosition) old, (XawTextPosition) old + 1, &text);
  173.            break;
  174.           }
  175.    }
  176.  
  177.  size = (int)strlen(buf);            /* now write the specified marker */
  178.  old = (buf[0] == '>') ? pos : pos + 1;
  179.  text.firstPos = 0;
  180.  text.length   = size;
  181.  text.ptr      = buf;
  182.  text.format   = FMT8BIT;
  183.  XawTextReplace(iw, (XawTextPosition) old, (XawTextPosition) old + size, &text);
  184.  
  185.  XawTextSetInsertionPoint(iw, pos);    /* reset our actual insertion point */
  186. } /* markIndex */
  187.  
  188.  
  189. /*
  190. ** @(#)LastNumber() - Get mail index number for last message in folder
  191. */
  192. int
  193. LastNumber(void)
  194. {
  195.  int            last_number;
  196.  Arg            args[1];
  197.  String            c, ep, str = NULL;
  198.  Widget            iw = XtNameToWidget(toplevel, "topBox.indexWindow");
  199.  
  200.  
  201.  XtSetArg(args[0], XtNstring, &str);
  202.  XtGetValues(iw, args, 1);
  203.  
  204.  ep = &str[(int)strlen(str) - 1];
  205.  
  206.  for (c = ep - 1; c > str; c--)
  207.      if (*(c - 1) == '\n' && *(c + 1) != 'D')
  208.         break;
  209.  
  210.  for (; c < ep && !isdigit(*c); c++);
  211.  (void) sscanf(c, "%d", &last_number);
  212.  
  213.  return(last_number);
  214. } /* LastNumber */
  215.  
  216.  
  217. /*
  218. ** @(#)SelectionNumber() - Get mail index number from line position
  219. */
  220. int
  221. SelectionNumber(int undeleting)
  222. {
  223.  Arg            args[1];
  224.  String            c, str = NULL;
  225.  Widget            iw = XtNameToWidget(toplevel, "topBox.indexWindow");
  226.  XawTextPosition    pos;
  227.  int            selection_number = 0;
  228.  
  229.  
  230.  XtSetArg(args[0], XtNstring, &str);
  231.  XtGetValues(iw, args, 1);
  232.  
  233.  for (pos = XawTextGetInsertionPoint(iw); pos > 0 && str[pos] != '\n'; pos--);
  234.  pos++;
  235.  
  236.  if (! undeleting || str[pos + 1] == 'D') {
  237.     for (c = &str[pos]; *c && !isdigit(*c); c++);
  238.     (void) sscanf(c, "%d", &selection_number);
  239.    }
  240.  
  241.  return(selection_number);
  242. } /* SelectionNumber */
  243.  
  244.  
  245. /* ARGSUSED */
  246. /*
  247. ** @(#)SetCursor() - sets the wait cursor or restores the default
  248. */
  249. void
  250. SetCursor(int waiting)
  251.                        /* a non-zero value sets the busy cursor */
  252. {
  253.  if (! waiting)
  254.     XUnmapWindow(XtDisplay(toplevel), WaitCursorWindow);
  255.  else {
  256.       XMapWindow(XtDisplay(toplevel), WaitCursorWindow);
  257.     Waiting = TRUE;        /* to prevent overwrite of important info */
  258.    }
  259.  
  260.  XFlush(XtDisplay(toplevel));
  261. } /* SetCursor */
  262.  
  263.  
  264. /*
  265. ** @(#)SetXY() - Set relative window coordinates including specified offset
  266. */
  267. void
  268. SetXY(Widget target, Widget reference, int X_offset, int Y_offset)
  269. {
  270.  Arg        args[2];
  271.  Display    *dpy = XtDisplay(reference);
  272.  
  273.  Window        dumy;
  274.  int        x, y;
  275.  
  276.  
  277.  XTranslateCoordinates(dpy, XtWindow(reference),
  278.                        RootWindow(dpy, DefaultScreen(dpy)),
  279.                        X_offset, Y_offset, &x, &y, &dumy);
  280.  /*
  281.  ** Keep window within root window borders (don't place it off-screen)
  282.  */
  283.  if (! XtIsRealized(target))
  284.     XtRealizeWidget(target);        /* to get width and height values */
  285.  
  286.  if (x + (int) target->core.width > RootWidth)
  287.     x = RootWidth - target->core.width - 2;
  288.  
  289.  if (y + (int)target->core.height > RootHeight)
  290.     y = RootHeight - target->core.height - 2;
  291.  
  292.  XtSetArg(args[0], XtNx, x);
  293.  XtSetArg(args[1], XtNy, y);
  294.  XtSetValues(target, args, 2);
  295. } /* end - SetXY */
  296.  
  297.  
  298. /*
  299. ** @(#)TextGetLastPos() - return position of last text character
  300. */
  301. XawTextPosition
  302. TextGetLastPos(Widget w)
  303. {
  304.  TextWidget ctx = (TextWidget) w;
  305.  if (ctx->text.source)
  306.      return (XawTextSourceScan(ctx->text.source,0,XawstAll,XawsdRight,1,TRUE));
  307.  else
  308.       return( (XawTextPosition) 0);
  309. }
  310.  
  311.  
  312. /*
  313. ** @(#)UpdateTitleBar() - replace information in the title bar title
  314. */
  315. void
  316. UpdateTitleBar(char *msg)
  317. {
  318.  char        message[BUFSIZ];
  319.  Arg        args[1];
  320.  Widget        w;
  321.  
  322.  
  323.  (void) sprintf(message, "%s%d - %s", TITLE, PATCHLEVEL, msg);
  324.  
  325.  w = XtNameToWidget(toplevel, "topBox.titleBar.title");
  326.  
  327.  XtSetArg(args[0], XtNlabel, (XtArgVal) message);
  328.  XtSetValues(w, args, 1);
  329.  
  330.  w = XtNameToWidget(toplevel, "topBox.commandPanel.Newmail.Newmail_menu.menu.inc");
  331.  if (w)
  332.     XtSetSensitive(w, In_System_Folder());
  333. } /* UpdateTitleBar */
  334.  
  335.  
  336. /*
  337. ** @(#)writeTo() - write data to the specified text widget
  338. */
  339. void
  340. writeTo(Widget w, char *data, int do_append)
  341. {
  342.  XawTextBlock        text;
  343.  XawTextPosition    startPos, endPos;
  344.  int            l, n;
  345.  
  346.  
  347.  endPos         = TextGetLastPos(w) + (do_append ? 0 : 1);
  348.  startPos       = (do_append ? endPos : 0);
  349.  text.firstPos  = 0;
  350.  text.length    = (int)strlen(data);
  351.  text.ptr       = data;
  352.  text.format    = FMT8BIT;
  353.  
  354.  XawTextReplace(w, (XawTextPosition) startPos, (XawTextPosition) endPos, &text);
  355.  
  356.  XawTextSetInsertionPoint(w, (XawTextPosition) TextGetLastPos(w));
  357.  
  358.  XawTextInvalidate(w, (XawTextPosition) 0, (XawTextPosition) endPos);
  359. } /* writeTo */
  360.  
  361.  
  362. /*
  363. ** @(#)writeText() - replace the current text string in the text window.
  364. **                 Also look for an X-Face: header and if found, display.
  365. */
  366. void
  367. writeText(char *buf)
  368. {
  369.  Arg            args[2];
  370.  Widget        w = XtNameToWidget(toplevel, "topBox.textWindow.text");
  371. #ifdef X_FACE
  372.  Pixmap        bits;
  373.  Dimension    rWidth;
  374.  Display        *dpy = XtDisplay(w);
  375.  Widget         fw;
  376.  Window         rw;
  377.  char           cb[1024], fb[2048], *ptr, *xface;
  378.  int            i, n, x, y;
  379. #endif
  380.  
  381.  if (buf && *buf) {
  382. #ifndef X_FACE
  383.     XtSetArg(args[0], XtNstring, buf);
  384.     XtSetValues(w, args, 1);
  385. #else
  386.     if (! (fw = XtNameToWidget(XtParent(w), "face"))) {
  387.        XtSetArg(args[0], XtNstring, buf);
  388.        XtSetValues(w, args, 1);
  389.        return;
  390.       }
  391.     /*
  392.     ** First, unmap any current picture.
  393.     **
  394.     ** Look for a line containing an 'X-Face:' header, followed by 72
  395.     ** characters of compressed data.  The second and any subsequent lines
  396.     ** will contain an initial space (which is ignored), followed by 79
  397.     ** characters of compressed data.  The last line may contain fewer than 79
  398.     ** characters.
  399.     **
  400.     ** The X-Face: header and any immediate whitespace (tabs or spaces) will be
  401.     ** removed, and the remaining line placed in the internal buffer (minus
  402.     ** any trailing newline).  On subsequent lines, initial whitespace will be
  403.     ** removed, and the remainder of the data appended to the buffer (minus any
  404.     ** trailing newline).
  405.     **
  406.     ** A blank line, a line without an initial whitespace character,or the
  407.     ** end of the input buffer will signify the end of the X-Face data.  That
  408.     ** buffer will then be uncompressed, and if the data was valid, displayed.
  409.     */
  410.  
  411.     if (XtIsManaged(fw))
  412.        XtUnmanageChild(fw);
  413.  
  414.     for (ptr = buf; *ptr; ptr++) {
  415.         if (*ptr == '\n'                    ||
  416.            strncmp(ptr, "Status:", 7) == 0  ||
  417.            strncmp(ptr, "X-Face:", 7) == 0) break;
  418.  
  419.         for (; *ptr && *ptr != '\n'; ptr++);
  420.        }
  421.  
  422.     if (! *ptr || strncmp(ptr, "X-Face:", 7) != 0) {
  423.        XtSetArg(args[0], XtNstring, buf);
  424.        XtSetValues(w, args, 1);
  425.        return;
  426.       }
  427.  
  428.     xface = ptr;    /* keep track of the start position of X-Face header */
  429.  
  430.     bzero(fb, 2048);
  431.     for (i = 0, ptr += 7; *ptr; ptr++) {
  432.         if (*ptr != ' ' && *ptr != '\t' && *ptr != '\n')
  433.            fb[i++] = *ptr;
  434.         if (*ptr == '\n' && *(ptr+1) && *(ptr+1) != ' ' && *(ptr+1) != '\t')
  435.            break;
  436.        }
  437.  
  438.     if (XMail.No_X_Hdr) {
  439.        if (*ptr) ptr++;
  440.        bcopy(ptr, xface, (int)strlen(ptr) + 1);    /* suppress the X-Face header */
  441.       }
  442.  
  443.     XtSetArg(args[0], XtNstring, buf);
  444.     XtSetValues(w, args, 1);
  445.  
  446.     if (uncompface(fb) >= 0) {
  447.        bzero(cb, 1024);
  448.        for (i = n = 0;i < 1024;) {
  449.            if (! sscanf(&fb[n], "%i%n", &x, &y)) break;
  450.            cb[i++] = revtable[(x >> 8) & 0xFF];
  451.            cb[i++] = revtable[x & 0xFF];
  452.            n += y;
  453.            while (fb[n] && (fb[n]==',' || fb[n]=='\n')) n++;
  454.           }
  455.  
  456.        XtSetArg(args[0], XtNwidth, &rWidth);
  457.        XtGetValues(XtParent(w), args, 1);
  458.  
  459.        if ( (int)rWidth > 0 ) 
  460.         n = (int) rWidth - 52; /* the width of the face minus 4 pixel inset */
  461.        else
  462.         n = 0;
  463.  
  464.        XtSetArg(args[0], XtNbitmap, &bits);
  465.        XtGetValues(fw, args, 1);
  466.        if (bits != None)
  467.           XFreePixmap(dpy, bits );
  468.  
  469.        rw = RootWindow(dpy, DefaultScreen(dpy));
  470.        bits = XCreateBitmapFromData(dpy, rw, cb, 48, 48);
  471.        XtSetArg(args[0], XtNbitmap, bits );
  472.        XtSetArg(args[1], XtNhorizDistance, n);
  473.        XtSetValues(fw, args, 2);
  474.  
  475.        XtManageChild(fw);
  476.       }
  477. #endif
  478.    }
  479. } /* writeText */
  480.